#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include "task.hpp"
#include <wait.h>
#include <cstring>
class ProcessPool
{
#define NUM 1034
#define N 2
static const size_t defaultnum = 10;
    struct ChildPro
    {
        pid_t _pid;
        int _fd;
        std::string _ChildName;
        ChildPro(pid_t pid,int fd,const std::string ChlidName)
            :_pid(pid),_fd(fd),_ChildName(ChlidName)
        {}
    };
public:
    ProcessPool(size_t n = defaultnum)
        :_num(0)
        ,_vv(new vtask)
    {
        std::vector<int> tmp;
        for(size_t i = 0;i < n;i++)
        {
            int fdarr[N];
            if(pipe(fdarr) == -1)
            {
                perror("pipe");
                exit(EXIT_FAILURE);
            }

            int pid = fork();
            if(pid < 0)
            {
                perror("frok");
                exit(EXIT_FAILURE);
            }
            else if(pid == 0)
            {
                close(fdarr[1]);
                for(auto a : tmp) close(a);
                dup2(fdarr[0],0);
                work();
            }

            close(fdarr[0]);
            char buff[NUM];
            int ret = snprintf(buff,sizeof(buff),"[%d]子进程:[%d]",(int)i,pid);
            buff[ret] = 0;
            _ppool.push_back(ChildPro(pid,fdarr[1],buff));
            tmp.push_back(fdarr[1]);
        }
    }

    void run(int n)
    {
        int fd = _ppool[_num]._fd;
        char buff[NUM];
        int ret = snprintf(buff,sizeof(buff),"%d",n);
        buff[ret] = 0;
        //std::cout << buff << std::endl;
        
        write(fd,buff,ret+1);
        if(++_num == _ppool.size())_num = 0;
    }

    void debug()
    {
        for(auto i : _ppool)
        {
            std::cout << i._ChildName << std::endl;
        }
    }

    void ExitPro()
    {
        for(auto& a : _ppool)
        {
            int fd = a._fd;
            char buff[NUM];
            int ret = snprintf(buff,sizeof(buff),"%s","结束进程");
            buff[ret] = 0;
            printf("结束进程pid[%d]\n",a._pid);
            write(fd,buff,ret + 1); 
        }

        for(size_t i = 0;i < _ppool.size();i++)
        {
            pid_t pid = wait(nullptr);
            std::cout << pid <<std::endl;
        }
        _ppool.clear();
    }

    ~ProcessPool()
    {
       if(!_ppool.empty())
        {
            ExitPro();
        }
    }
private:
    void work()
    {
        while(true)
        {
            char buff[NUM];
            read(0,buff,sizeof(buff));
            if(strcmp(buff,"结束进程") == 0)
            {
                printf("pid[%d]\n",getpid());
                exit(0);
            }
            int cmd = buff[0] - '0';
            _vv->v[cmd]();
            sleep(1);
        }
    }
    size_t _num;
    vtask* _vv;
    std::vector<ChildPro> _ppool;
    
};